CanvasRenderingContext2D.prototype.drawLeftText = function(s, x, y, w) {
  this.textAlign = "left";
  var words = this.getWords(s);
  var fh = this.getFontHeight();
  var offset = x;
  for (var i = 0; i < words.length; i++) {
    if (x + w < offset + words[i].width) {
      offset = x;
      y = y + fh * 1.25;
    }
    this.font = words[i].font;
    this.fillText(words[i].s, offset, y, null);
    offset = offset + words[i].width;
  }
}

CanvasRenderingContext2D.prototype.drawCenterText = function(s, x, y, w) {
  this.textAlign = "left";
  var words = this.getWords(s);
  var fh = this.getFontHeight(this);
  var lines = new Array();
  var line = new Object();
  line.width = 0;
  line.words = new Array();
  for (var i = 0; i < words.length; i++) {
    if (line.width + words[i].width > w) {
      lines.push(line);
      line = new Object();
      line.width = 0;
      line.words = new Array();
    }
    line.words.push(words[i]);
    line.width = line.width + words[i].width;
  }
  lines.push(line);
  for (var j = 0; j < lines.length; j++) {
    line = lines[j];
    var offset = x - line.width / 2;
    for (var k = 0; k < line.words.length; k++) {
      var word = line.words[k];
      this.font = word.font;
      this.fillText(word.s, offset, y, null);
      offset = offset + word.width;
    }
    y = y + fh * 1.25;
  }
}

function Word(s, font, width) {
  this.s = s;
  this.font = font;
  this.width = width;
}

CanvasRenderingContext2D.prototype.getWords = function(s) {
  var words = new Array();
  var split = split2(s);
  for (var i in split) {
    split[i] = this.processHTML(split[i]);
    if (split[i].length > 0) {
      var measure = this.measureText(split[i] + (i + 1 == words.length ? "" : " "));
      words.push(new Word(split[i], this.font, measure.width));
    }
  }
  return words;
}

function split2(s) {
  var split = new Array();
  var offset = 0;
  for (var i = 0; i < s.length; i++) {
    if (s[i] == '<' && offset != i) {
      split.push(s.substring(offset, i));
      offset = i;
    } else if (s[i] == '>') {
      split.push(s.substring(offset, i + 1));
      offset = i + 1;
    } else if (s[i] == ' ') {
      if (offset != i) {
        split.push(s.substring(offset, i));
      }
      offset = i + 1;
    } else if (i == s.length - 1) {
      split.push(s.substring(offset, i + 1));
    }
  }
  return split
}

CanvasRenderingContext2D.prototype.getFontHeight = function() {
  var px = this.font.split(" ")[0];
  return parseInt(px.substring(0, px.length - 2));
}

CanvasRenderingContext2D.prototype.processHTML = function(s) {
  for (var i in s) {
    i = parseInt(i);
    if (s[i] == '<' && s[i + 2] == '>') {
      if (s[i + 1] == "b") {
        this.bold(true);
      } else if (s[i + 1] == "i") {
        this.italic(true);
      } else if (s[i + 2] == "u") {
        this.underline(true);
      }
      return this.processHTML(s.substring(0, i) + s.substring(i + 3));
    } else if (s[i] == '<' && s[i + 1] == '/' && s[i + 3] == '>') {
      if (s[i + 2] == "b") {
        this.bold(false);
      } else if (s[i + 2] == "i") {
        this.italic(false);
      } else if (s[i + 2] == "u") {
        this.underline(false);
      }
      return this.processHTML(s.substring(0, i) + s.substring(i + 4));
    }
  }
  return s;
}

CanvasRenderingContext2D.prototype.bold = function(b) {
  if (b && this.font.indexOf("bold ") < 0) {
    this.font = "bold " + this.font;
  } else if (!b && this.font.indexOf("bold ") >= 0){
    var i = this.font.indexOf("bold ");
    this.font = this.font.substring(0, i) + this.font.substring(i + "bold ".length);
  }
}

CanvasRenderingContext2D.prototype.italic = function(b) {
  if (b && this.font.indexOf("italic ") < 0) {
    this.font = "italic " + this.font;
  } else if (!b && this.font.indexOf("italic ") >= 0){
    var i = this.font.indexOf("italic ");
    this.font = this.font.substring(0, i) + this.font.substring(i + "italic ".length);
  }
}

CanvasRenderingContext2D.prototype.underline = function(b) {
  if (b) {

  } else {

  }
}